package ru.myrtle.umf.tools.ugen.templates;

import java.io.*;
import java.text.*;
import java.util.*;
import ru.myrtle.umf.*;
import ru.myrtle.umf.codegen.*;
import ru.myrtle.umf.codegen.java.*;
import ru.myrtle.umf.tools.ugen.*;

public class UFactoryTemplate extends UTemplate
{
    protected final String NL = System.getProperties().getProperty("line.separator");
    protected final String TEXT_1 = "package ";
    protected final String TEXT_2 = ";" + NL + NL;
    protected final String TEXT_3 = NL + "public final class ";
    protected final String TEXT_4 = " extends UFactoryImpl {" + NL + NL + "    public static final ";
    protected final String TEXT_5 = " INSTANCE;" + NL + NL + "    static {" + NL + "        INSTANCE = new ";
    protected final String TEXT_6 = "();" + NL + "        INSTANCE.setName(\"";
    protected final String TEXT_7 = "\");" + NL + "        INSTANCE.setDescription(\"";
    protected final String TEXT_8 = "\");" + NL + "    }" + NL + NL;
    protected final String TEXT_9 = "    public final ";
    protected final String TEXT_10 = " ";
    protected final String TEXT_11 = "() {" + NL + "        return new ";
    protected final String TEXT_12 = "();" + NL + "    }" + NL + "    " + NL;
    protected final String TEXT_13 = "    public UObject createInstance(UClass uClass) {" + NL;
    protected final String TEXT_14 = "        if (uClass == ";
    protected final String TEXT_15 = ".";
    protected final String TEXT_16 = ") {" + NL + "            return ";
    protected final String TEXT_17 = "();" + NL + "        }" + NL;
    protected final String TEXT_18 = NL + "        return super.createInstance(uClass);" + NL + "    }" + NL + NL;
    protected final String TEXT_19 = "    public ";
    protected final String TEXT_20 = " ";
    protected final String TEXT_21 = "(String source) {" + NL + "        Object _object_ = ";
    protected final String TEXT_22 = ".INSTANCE.convertFromString(" + NL + "            source" + NL + "        );" + NL + "        return ";
    protected final String TEXT_23 = ";" + NL + "    }" + NL + NL + "    public String ";
    protected final String TEXT_24 = "(";
    protected final String TEXT_25 = " source) {" + NL + "        return ";
    protected final String TEXT_26 = ".INSTANCE.convertToString(source);" + NL + "    }" + NL + NL;
    protected final String TEXT_27 = "    /**" + NL + "     * Creates an instance of the data type from the literal value." + NL + "     *" + NL + "     * @param uDataType the data type of the value." + NL + "     * @param literalValue literal value of the instance." + NL + "     * @return an instance of the data type." + NL + "     */" + NL + "    public Object convertFromString(UDataType uDataType, String literalValue) {" + NL;
    protected final String TEXT_28 = "        if (uDataType == ";
    protected final String TEXT_29 = ".";
    protected final String TEXT_30 = ") {" + NL + "            return ";
    protected final String TEXT_31 = "(literalValue);" + NL + "        }" + NL;
    protected final String TEXT_32 = NL + "        return super.convertFromString(uDataType, literalValue);" + NL + "    }" + NL + NL + "    /**" + NL + "     * Returns the literal value of the instance." + NL + "     *" + NL + "     * @param uDataType the data type of the value." + NL + "     * @param instanceValue the value." + NL + "     * @return the literal value of the instance." + NL + "     */" + NL + "    public String convertToString(UDataType uDataType, Object instanceValue) {" + NL;
    protected final String TEXT_33 = "        if (uDataType == ";
    protected final String TEXT_34 = ".";
    protected final String TEXT_35 = ") {" + NL + "            return ";
    protected final String TEXT_36 = "((";
    protected final String TEXT_37 = "));" + NL + "        }" + NL;
    protected final String TEXT_38 = NL + "        return super.convertToString(uDataType, instanceValue);" + NL + "    }" + NL + "    " + NL + "}" + NL;

    /*
     *
     */


    public UFactoryTemplate() {

    }

    /*
     *
     */

    public String generate(UTemplateContext context) throws UTemplateRejectException
    {
        final StringBuffer stringBuffer = new StringBuffer();

    checkTemplateObjectType(context, UPackage.class);

    UPackage object = (UPackage) context.getObject();

    String modelClassName    = UGenUtil.getModelClassName(object);
    String modelClassPackage = UGenUtil.getModelClassPackage(object);

    String factoryClassName     = UGenUtil.getFactoryClassName(object);
    String factoryClassPackage  = UGenUtil.getFactoryClassPackage(object);

    context.getResource().setObjectFileName(factoryClassName);
    context.getResource().setObjectFileExtension("java");
    context.getResource().setObjectPackage(factoryClassPackage);

    JavaImportBuilder importBuilder = new JavaImportBuilder();

    importBuilder.addPackage("ru.myrtle.umf");
    importBuilder.addPackage(modelClassPackage);
    importBuilder.addPackage(
        UGenUtil.getObjectImplClassPackage(UModel.UFACTORY)
    );

    createDoc();
    addDocDescription(
            object.getDescription()
    );
    addDocAnnotation("generated");

        stringBuffer.append(TEXT_1);
        stringBuffer.append(factoryClassPackage);
        stringBuffer.append(TEXT_2);
        stringBuffer.append(getDocString());
        stringBuffer.append(TEXT_3);
        stringBuffer.append(factoryClassName);
        stringBuffer.append(TEXT_4);
        stringBuffer.append(factoryClassName);
        stringBuffer.append(TEXT_5);
        stringBuffer.append(factoryClassName);
        stringBuffer.append(TEXT_6);
        stringBuffer.append(factoryClassName);
        stringBuffer.append(TEXT_7);
        stringBuffer.append(factoryClassName);
        stringBuffer.append(TEXT_8);

    for (UClass klass : object.getClasses()) {
        if (klass.isVirtual()) {
            continue;
        }

        String methodName = "create" + UGenUtil.capName(klass.getName());

        String implClassName    = UGenUtil.getObjectImplClassName(klass);
        String implClassPackage = UGenUtil.getObjectImplClassPackage(klass);

        importBuilder.addPackage(
            implClassPackage
        );

        stringBuffer.append(TEXT_9);
        stringBuffer.append(klass.getName());
        stringBuffer.append(TEXT_10);
        stringBuffer.append(methodName);
        stringBuffer.append(TEXT_11);
        stringBuffer.append(implClassName);
        stringBuffer.append(TEXT_12);

    }

        stringBuffer.append(TEXT_13);

    for (UClass klass : object.getClasses()) {
        if (klass.isVirtual()) {
            continue;
        }

        String literal    = UGenUtil.getClassifierLiteral(klass);
        String methodName = "create" + UGenUtil.capName(klass.getName());

        stringBuffer.append(TEXT_14);
        stringBuffer.append(modelClassName);
        stringBuffer.append(TEXT_15);
        stringBuffer.append(literal);
        stringBuffer.append(TEXT_16);
        stringBuffer.append(methodName);
        stringBuffer.append(TEXT_17);

    }

        stringBuffer.append(TEXT_18);

    for (UDataType dataType : object.getDataTypes()) {
        if (!dataType.isSerializable()) {
            continue;
        }

        String dataTypeName = dataType.getName();
        String type = UGenUtil.getInstanceTypeName(dataType, importBuilder);

        String from_string = "convert" + UGenUtil.capName(dataTypeName) + "FromString";
        String to_string = "convert" + UGenUtil.capName(dataTypeName) + "ToString";

        String converterClassName    = UGenUtil.getConverterClassName(dataType);
        String converterClassPackage = UGenUtil.getConverterClassPackage(dataType);

        importBuilder.addPackage(converterClassPackage);

        String conversionExpression = UGenUtil.createConversionExpressionForType(
            dataType, type, "_object_"
        );

        stringBuffer.append(TEXT_19);
        stringBuffer.append(type);
        stringBuffer.append(TEXT_20);
        stringBuffer.append(from_string);
        stringBuffer.append(TEXT_21);
        stringBuffer.append(converterClassName);
        stringBuffer.append(TEXT_22);
        stringBuffer.append(conversionExpression);
        stringBuffer.append(TEXT_23);
        stringBuffer.append(to_string);
        stringBuffer.append(TEXT_24);
        stringBuffer.append(type);
        stringBuffer.append(TEXT_25);
        stringBuffer.append(converterClassName);
        stringBuffer.append(TEXT_26);

    }

        stringBuffer.append(TEXT_27);

    for (UDataType dataType : object.getDataTypes()) {
        if (!dataType.isSerializable()) {
            continue;
        }

        String dataTypeName = dataType.getName();
        String literal = UGenUtil.getClassifierLiteral(dataType);
        String from_string = "convert" + UGenUtil.capName(dataTypeName) + "FromString";

        stringBuffer.append(TEXT_28);
        stringBuffer.append(modelClassName);
        stringBuffer.append(TEXT_29);
        stringBuffer.append(literal);
        stringBuffer.append(TEXT_30);
        stringBuffer.append(from_string);
        stringBuffer.append(TEXT_31);

    }

        stringBuffer.append(TEXT_32);

    for (UDataType dataType : object.getDataTypes()) {
        if (!dataType.isSerializable()) {
            continue;
        }

        String dataTypeName = dataType.getName();
        String type = UGenUtil.getInstanceTypeName(dataType, importBuilder);
        String literal = UGenUtil.getClassifierLiteral(dataType);
        String to_string = "convert" + UGenUtil.capName(dataTypeName) + "ToString";

        String conversionExpression = UGenUtil.createConversionExpressionForType(
            dataType, type, "instanceValue"
        );

        stringBuffer.append(TEXT_33);
        stringBuffer.append(modelClassName);
        stringBuffer.append(TEXT_34);
        stringBuffer.append(literal);
        stringBuffer.append(TEXT_35);
        stringBuffer.append(to_string);
        stringBuffer.append(TEXT_36);
        stringBuffer.append(conversionExpression);
        stringBuffer.append(TEXT_37);

    }

        stringBuffer.append(TEXT_38);

    insertImport(stringBuffer, importBuilder, factoryClassPackage);


        return stringBuffer.toString();
    }

    // ---------------------------------------------------------------------------------------
    // ---------------------------------------------------------------------------------------

}
